package com.aci.test.wordfreq.sort.impl;

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;

import com.aci.test.wordfreq.sort.IWordsSorter;
import com.google.common.collect.Maps;

public class ByFrequencySorter implements IWordsSorter {

	private boolean asc;

	public ByFrequencySorter(boolean asc) {
		this.asc = asc;
	}

	@Override
	public Iterable<String> sort(Iterator<String> words) {
		Map<String, Integer> frequencyMap = buildFrequencyMap(words);
		Map<String, Integer> sortedMap = sort(frequencyMap);
		return sortedMap.keySet();
	}

	private Map<String, Integer> sort(final Map<String, Integer> frequencyMap) {
		Comparator<String> frequencyComparator = new Comparator<String>() {

			@Override
			public int compare(String o1, String o2) {
				Integer o1Frequency = frequencyMap.get(o1);
				Integer o2Frequency = frequencyMap.get(o2);
				int naturalSortResult = (o1Frequency < o2Frequency) ? -1 : ((o1Frequency == o2Frequency) ? 0 : 1);
				return asc ? naturalSortResult : (-1) * naturalSortResult;
			}
		};
		Map<String, Integer> sortedMap = Maps.newTreeMap(frequencyComparator);
		sortedMap.putAll(frequencyMap);
		return sortedMap;
	}

	private Map<String, Integer> buildFrequencyMap(Iterator<String> words) {
		Map<String, Integer> frequencyMap = Maps.newHashMap();
		while (words.hasNext()) {
			String word = words.next();
			if (frequencyMap.containsKey(word)) {
				Integer frequency = frequencyMap.get(word);
				frequencyMap.put(word, ++frequency);
			} else {
				frequencyMap.put(word, 0);
			}
		}
		return frequencyMap;
	}

}
